iT邦幫忙

2021 iThome 鐵人賽

DAY 20
2
Modern Web

JavaScript Easy Go!系列 第 20

#20 Telegram Bot Webhook 訊息收發

  • 分享至 

  • xImage
  •  

今天來嘗試部署 Cloudflare Workers 並寫寫看簡單的信息收發。

response

如果你仔細看我們昨天寫的 main.js,你會發現我們在回傳時用 response 函式包起來,但我們並沒有寫他啊?
沒錯,所以我們今天要建立一個 response.js 並在 main.js 引用其中的 response 函式。

首先,我們先在 response.js 中建立 response 函式,它的目的是為了要處理 CORS 的問題,幫我們處理好麻煩的 Headers 就不需要每次回傳請求都重複加上去了:

// response.js
function response({ data = "", status = 200, headers = {} }) {
    let header = new Headers();
    header.append("Content-Type", "application/json; charset=utf-8");
    header.append("Access-Control-Allow-Origin", "*");
    header.append("Access-Control-Allow-Headers", "*");
    header.append("Access-Control-Allow-Methods", "*");
    header.append("Access-Control-Allow-Credentials", "true");
    header.append("Cache-Control", "max-age=60, s-maxage=60");
    header.append("Cross-Origin-Resource-Policy", "cross-origin");
    for (let h of Object.keys(headers)) header.append(h, headers[h]);

    return new Response(data, {
        status,
        headers: header,
    });
}

export default response;

我們在這裡加上一堆 Header 來處理 CORS 的問題,讓所有網站都可以請求 (不過在這裡其實不是那麼必要啦),並告訴別人我們回傳的是 JSON。

接著在 main.js 引入:

import response from "./response";

wrangler

好了,接下來我們來試試 wrangler 的功能吧。

先用 wrangler login 登入。

然後我們在 wrangler.toml 中加上一行:

webpack_config = "webpack.config.js"

這樣 wrangler 在 build 的時候就會套用我們 webpack.config.js 中的設定了。

wrnagler dev

接著我們來用用看 wrangler dev,它會在本機建立一個開發預覽用的網頁,你就可以透過它向你寫的 Worker 發送請求了。
在使用 wrangler dev 時,如果你的 worker 沒寫好發生錯誤,也可以在 Terminal 看到錯誤訊息,方便偵錯與除錯。

wrangler dev 建立的 127.0.0.1:8787 發送請求試試:

{
  "cf": {
    "clientTcpRtt": 1,
    "longitude": "121.53240",
    "latitude": "25.05040",
    "tlsCipher": "ECDHE-ECDSA-AES128-GCM-SHA256",
    "continent": "AS",
    "asn": 3462,
    "clientAcceptEncoding": "gzip",
    "country": "TW",
    ...
}

這串 JSON 就是你對 Worker 發送的請求所包含的資訊,以及 Worker 的資訊,像是由何處的 Worker 回應的。

wrangler publish

當覺得 Worker 寫到一個段落要部署到 Edge 上時,就使用 wrangler publish,如果你有在 wrangler.toml 設定 KV 或是 Cron,它也會在這時一並設定。

執行完後它就會告訴你你的 Worker 位置在哪裡了。

建立 Telegram Bot

首先我們得先建立一個 Telegram Bot。
建立的方法很奇特,就是在 Telegram 裡向 @BotFather 傳指令訊息。

注意,其中的 Token 是用來控制 Bot 的,不能外流。 如果不小心外流可以用 /revoke 來更換一個新的 Token。

這樣就建立好 Bot 了,那要怎麼設定 Webhook 呢?
我們可以用 Telegram 的 REST API 設定 Webhook:

URL = `https://api.telegram.org/bot${token}/setWebhook?url=${webhook_url}`

我們在這裡將 webhook_url 設為我們 Worker Root + /webhook
發送訊息後,如果 Telegram 回傳這個就代表設定成功:

{"ok":true,"result":true,"description":"Webhook was set"}

然後我們回到我們的 main.js 新增程式來接收 webhook 收到的訊息:

// 我們會收到 Telegram 的 POST 請求
router.post("/webhook", async (request) => {
    return response({ status: 200 });
});

記住要寫在 router.all("*", ... 前面會優先套用規則。
然後一定要回傳 HTTP CODE 200,要不然 Telegram 會以為你沒收到一直戳你。
Telegram 的文件中都有說明它會透過 webhook 傳的格式:文件#update
我們在意的是 Update 中的 Message,文件中也有寫到格式:文件#message

我們這樣寫來收發訊息:

router.post("/webhook", async (request) => {
    // 拿到 Webhook 的 JSON 格式資料
    const body = await request.json();

    // 因為不只有 Telegram 可以透過該網址傳訊息,所以要確認訊息格式是否正確
    if (body.message && body.message.chat && body.message.chat.id && body.message.text) {
        // 我們在乎的是訊息內容及訊息來源
        const text = body.message.text;
        const chat_id = body.message.chat.id;

        // 回覆訊息,POST
        await fetch(`https://api.telegram.org/bot${TOKEN}/sendMessage`, {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            // 用 Markdown 格式回傳顛倒的訊息
            body: JSON.stringify({ chat_id, parse_mode: "MarkdownV2", text: text.split("").reverse().join("") }),
        });
    }

    // 告訴 Telegram 我們收到了
    return response({ status: 200 });
});

在我們收到訊息後會回傳覆相反的文字。
在上方程式中我們有一個 TOKEN 要用環境變數帶入,在 wrangler.toml 最下方新增:

[vars]
TOKEN = "BOT_TOKEN"

接著讓我們 wrangler publish 上去!

成功!

接下來

接下來讓我們的 Automation 在有空位的時候通知我們!


每日鐵人賽熱門 Top 10 (1003)

以 10/03 20:00 ~ 10/04 20:00 文章觀看數增加值排名

  1. +281 JS 07 - 原型方法:欲達則必速
    • 作者: Felix
    • 系列:JavaScript 從 50% 開始,打造函式庫不是問題!
  2. +172 [Day28] 戲弄老闆! 教你用Machine Learning將老闆玩弄於股掌之間!
    • 作者: lulu_meat
    • 系列:奇怪的知識增加了!原來程式還可以這樣用?!
  3. +158 Day 22網路程式設計
    • 作者: weiting_0826
    • 系列:一起學Flutter,和我變Better!
  4. +150 Proxmox VE 客體機磁碟遷移
    • 作者: Jason Cheng (節省哥)
    • 系列:突破困境:企業開源虛擬化管理平台
  5. +146 Day 1 無限手套 AWS 版:掌控一切的 5 + 1 雲端必學主題
    • 作者: 用圖片高效學程式
    • 系列:無限手套 AWS 版:掌控一切的 5 + 1 雲端必學主題
  6. +138 Android學習筆記25
    • 作者: blossomgp3
    • 系列:Android kotlin &MVVM
  7. +123 從零開始的8-bit迷宮探險【Level 26】這遊戲沒有華佗,不能補血啊!Game Over 場景切換
    • 作者: 雪花冰
    • 系列:從零開始的8-bit迷宮探險!Swift SpriteKit 遊戲開發實戰
  8. +118 終章 - 資安碎碎念與心得
    • 作者: John醬
    • 系列:網路奇妙物語 - IT&Security
  9. +115 爬蟲怎麼爬 從零開始的爬蟲自學 DAY20 網路爬蟲開爬-3抓取整頁標題
    • 作者: 早安您好
    • 系列:爬蟲怎麼爬 從零開始的爬蟲自學
  10. +112 [面試][資料庫]關連式資料庫要如何設計避免超賣?
    • 作者: 寶寶出頭天
    • 系列:全端工程師生存筆記

還剩 10 天!!


上一篇
#19 Telegram Bot 起手式
下一篇
#21 讓 Automation 與 Chat Bot 連動
系列文
JavaScript Easy Go!31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言